package br.pucrio.inf.les.SPLAnalyser.impl.squidplugin.extractor;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;

import br.pucrio.inf.les.genarch.models.configuration.Configuration;
import br.pucrio.inf.les.genarch.models.configuration.ConfigurationClass;
import br.pucrio.inf.les.genarch.models.configuration.ConfigurationCodePiece;
import br.pucrio.inf.les.genarch.models.configuration.ConfigurationField;
import br.pucrio.inf.les.genarch.models.configuration.ConfigurationMethod;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.Class;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.CodePiece;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.Feature;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.Field;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.Method;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.SquidModel;
import br.ufrn.dimap.ase.squid.core.models.util.SquidModelContent;

public class ConfigurationKnowledgeExtractor {

	private SquidModelContent analysisModelContent;
	private Configuration configuration;
	public ConfigurationKnowledgeExtractor(Configuration configuration,
			SquidModel analysisModel) {
		this.configuration = configuration;
		analysisModelContent = new SquidModelContent(analysisModel);
		
	}

	public SquidModel extract() {
		TreeIterator configurationContents = configuration.getMappingRelationships().eAllContents();
		
		while ( configurationContents.hasNext() ) {
			EObject o = (EObject)configurationContents.next();
			
			
			o.getClass();
			if ( o instanceof ConfigurationField) {				
				ConfigurationField entity = (ConfigurationField)o;
					
				Field field = analysisModelContent.findField(entity.getName(), pathTranslator(entity.getPath()));
				if(field == null){
//					System.out.println("NULL 6 erro field em enum");
					
				}else{
					List<Feature> features = new ArrayList<Feature>();
					List<String> expressionFeatures = expressionToFeature(entity.getFeatureExpression().getExpression());
					for(String featureName : expressionFeatures){
						Feature feature = analysisModelContent.findFeature(analysisModelContent.getAnalysisModel().getFeaturesReference()
								, featureName);
						
						analysisModelContent.addMapping(feature, field, null, entity.getFeatureExpression().getExpression());
					}
				}
			} else if (o instanceof ConfigurationClass ) {
				
				ConfigurationClass entity = (ConfigurationClass)o;
				Class clazz = analysisModelContent.findClass(entity.getName(), classPathTranslator(entity.getPath(), entity.getName()));
				List<String> expressionFeatures = expressionToFeature(entity.getFeatureExpression().getExpression());
				for(String featureName : expressionFeatures){
					Feature feature = analysisModelContent.findFeature(analysisModelContent.getAnalysisModel().getFeaturesReference()
							, featureName);
					analysisModelContent.addMapping(feature, clazz, null,entity.getFeatureExpression().getExpression());
				}
				
			} else if (o instanceof ConfigurationMethod) {
				
				
				ConfigurationMethod entity = (ConfigurationMethod)o;
				
				
				Method method = analysisModelContent.findMethod(entity.getName(), pathTranslator(entity.getPath()) );
				
				
				if(method == null){ // Is not a method, probably is a inner class, GENARCH is donkey and doesn't know this.  
					continue;
				}
				
				
				
				List<String> expressionFeatures = expressionToFeature(entity.getFeatureExpression().getExpression());
				for(String featureName : expressionFeatures){
					Feature feature = analysisModelContent.findFeature(analysisModelContent.getAnalysisModel().getFeaturesReference()
							, featureName);
					if(method == null)
						System.out.println("OPA");
					analysisModelContent.addMapping(feature, method, null, entity.getFeatureExpression().getExpression());
				}
				for(Object piece : entity.getCodePieces()){
					navigateCodePieces((ConfigurationCodePiece) piece);
				}
				
			} else {
				continue;
			}
		}
		return analysisModelContent.getAnalysisModel();
	}
	
	public void navigateCodePieces(ConfigurationCodePiece piece){
		CodePiece codePiece = analysisModelContent.findCodePiece( pathTranslator(piece.getPath()) );
		List<String> expressionFeatures = expressionToFeature(piece.getFeatureExpression().getExpression());
		for(String featureName : expressionFeatures){
			Feature feature = analysisModelContent.findFeature(analysisModelContent.getAnalysisModel().getFeaturesReference()
					, featureName);
			analysisModelContent.addMapping(feature, codePiece, null, piece.getFeatureExpression().getExpression());
		}
		for(Object child : piece.getCodePieces()){
			navigateCodePieces((ConfigurationCodePiece) child);
		}	
	}
	
	public List<String> expressionToFeature(String expression){
		List<String> result = new ArrayList<String>();
		
	     Scanner s = new Scanner(expression).useDelimiter("\\s* and \\s*");
	    
	     while (s.hasNext()) {
				result.add(s.next());
			}
		return result;
	}
	
	public String classPathTranslator(String path, String name){
		String newPath = "";
		newPath = path.substring(path.indexOf("/")+1, path.length());
		newPath = newPath.replaceAll("(/)",".");
		newPath = newPath.replace("."+name,"");
		return newPath;
	}
	public String pathTranslator(String path){
		String newPath = "";
		newPath = path.substring(path.indexOf("/")+1, path.length());
		newPath = newPath.replaceAll("(/)",".");
		newPath = newPath.replace(".java","");
		return newPath;

	}
	
	

}
